package com.m1.tzolkin.model;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.m1.tzolkin.model.buildables.ActionBuilding;
import com.m1.tzolkin.model.buildables.Farm;
import com.m1.tzolkin.model.buildables.IActionBuilding;
import com.m1.tzolkin.model.buildables.IFarm;
import com.m1.tzolkin.model.buildables.IMonument;
import com.m1.tzolkin.model.buildables.IZonedBuilding;
import com.m1.tzolkin.model.buildables.Monument;
import com.m1.tzolkin.model.exceptions.NoAvailableSkullException;

public class Bank implements IBank {
	
	// ATTRIBUTS
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -4445650758197264410L;

	public static final int DEFAULT_SKULLS = 13;
	
	private int skulls;
	private final List<Collection<IFarm>> farms;
	private final List<Collection<IActionBuilding>> buildings;
	private int period;
	private final Collection<IMonument> monuments;
	
	private final PropertyChangeSupport listeners;
	
	// CONSTRUCTEUR
	
	public Bank() {
		skulls = DEFAULT_SKULLS;
		farms = new ArrayList<Collection<IFarm>>();
		buildings = new ArrayList<Collection<IActionBuilding>>();
		for (int i = 0; i < 2; ++i) {
			farms.add(i, Farm.createAll(i));
			buildings.add(i, ActionBuilding.createAll(i));
		}
		monuments = Monument.createAll();
		period = 0;
		listeners = new PropertyChangeSupport(this);
	}
	
	// REQUETES
	
	@Override
	public PropertyChangeListener[] getPropertyChangeListeners() {
		return listeners.getPropertyChangeListeners();
	}
	
	@Override
	public int getSkulls() {
		return skulls;
	}

	@Override
	public IZonedBuilding getBuilding() {
		IZonedBuilding b;
		int farmsSize = farms.get(period).size(),
			buildingsSize = buildings.get(period).size();
		if ((int) ((farmsSize + buildingsSize) * Math.random()) < farmsSize) {
			b = searchFarm();
		} else {
			b = searchBuilding();
		}
		if (b == null) {
			b = searchFarm();
		}
		return b;
	}

	@Override
	public IMonument getMonument() {
		if (!monuments.isEmpty()) {
			int n = (int) (monuments.size() * Math.random());
			int i = 0;
			for (IMonument b : monuments) {
				if (i == n) {
					monuments.remove(b);
					return b;
				}
				++i;
			}
		}
		return null;
	}
	
	// COMMANDES
	
	@Override
	public void addPropertyChangeListener(PropertyChangeListener l) {
		listeners.addPropertyChangeListener(l);
	}
	
	@Override
	public void removePropertyChangeListener(PropertyChangeListener l) {
		listeners.removePropertyChangeListener(l);
	}
	
	@Override
	public void takeSkull() throws NoAvailableSkullException {
		if (skulls <= 0) {
			throw new NoAvailableSkullException();
		}
		--skulls;
		listeners.firePropertyChange("skulls", skulls + 1, skulls);
	}
	
	@Override
	public void setSecondPeriod() {
		period = 1;
	}
	
	// OUTILS
	
	private IFarm searchFarm() {
		if (!farms.get(period).isEmpty()) {
			int n = (int) (farms.get(period).size() * Math.random());
			int i = 0;
			for (IFarm f : farms.get(period)) {
				if (i == n) {
					farms.get(period).remove(f);
					return f;
				}
				++i;
			}
		}
		return null;
	}
	
	private IActionBuilding searchBuilding() {
		int n = (int) (buildings.get(period).size() * Math.random());
		int i = 0;
		for (IActionBuilding b : buildings.get(period)) {
			if (i == n) {
				buildings.get(period).remove(b);
				return b;
			}
			++i;
		}
		return null;
	}

}
